package com.lion.hbase.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 反射工具类
 * 
 * @author 李永曜
 * @time 2014-4-25下午01:20:39
 */
public class ReflectUtil {
	private static final Log LOG = LogFactory.getLog(TimeUtil.class);
	/**
	 * 获得属性名
	 * 
	 * @param object
	 * @return
	 */
	public static List<String> componentsName(Object object) {
		Field[] fields = object.getClass().getDeclaredFields();
		List<String> filedName = new ArrayList<String>();
		for (int i = 0; i < fields.length; i++) {
			String varName = fields[i].getName();
			boolean accessFlag = fields[i].isAccessible();
			fields[i].setAccessible(true);
			filedName.add(varName);
			fields[i].setAccessible(accessFlag);

		}
		return filedName;
	}

	/**
	 * 获得属性类型
	 * 
	 * @param object
	 * @return
	 */
	public static Class<?> componentsType(String field,Class<?> clazz) {
		Field[] fields = clazz.getDeclaredFields();
		Class<?> type = null;
		for (int i = 0; i < fields.length; i++) {
			if(fields[i].getName().equals(field)){
				boolean accessFlag = fields[i].isAccessible();
				fields[i].setAccessible(true);
				type = fields[i].getType();
				fields[i].setAccessible(accessFlag);
			}
		}
		return type;
	}
	
	/**
	 * 获取键值对
	 * 
	 * @param object
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	public static Map<String, Object> componentsNameAndValue(Object object)
			throws IllegalArgumentException, IllegalAccessException {
		Field[] fields = object.getClass().getDeclaredFields();
		Map<String, Object> nameAndValue = new HashMap<String, Object>();
		List<String> filedName = new ArrayList<String>();
		List<Object> filedValue = new ArrayList<Object>();
		for (int i = 0; i < fields.length; i++) {
			boolean accessFlag = fields[i].isAccessible();
			fields[i].setAccessible(true);
			String varName = fields[i].getName();
			Object varValue = fields[i].get(object);
			filedName.add(varName);
			filedValue.add(varValue);
			fields[i].setAccessible(accessFlag);
		}
		nameAndValue.put("value", filedValue);
		nameAndValue.put("key", filedName);
		return nameAndValue;
	}
	
	/**
	 * 获取键值对
	 * 
	 * @param object
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	public static Map<String, Object> componentsNameAndValueByMethod(Object object)
			throws IllegalArgumentException, IllegalAccessException {
		Method[] fields = object.getClass().getDeclaredMethods();
		Map<String, Object> nameAndValue = new HashMap<String, Object>();
		for (int i = 0; i < fields.length; i++) {
			fields[i].setAccessible(true);
			String varName = fields[i].getName();
			if(varName.startsWith("get")){
				String name = varName.substring(3);
				name = String.valueOf(name.charAt(0)).toLowerCase()+name.substring(1);
				try {
					Object value = fields[i].invoke(object);
					nameAndValue.put(name, value);
				} catch (InvocationTargetException e) {
					LOG.error(e, e);
				}
			}
		}
		return nameAndValue;
	}

	/**
	 * 根据属性名称查找对象中的相应值
	 * 
	 * @param name
	 *            属性名
	 * @param object
	 *            要查找的对象
	 * @return Object 返回属性对应的值
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 */
	public static Object getValueByName(String name, Object object)
			throws IllegalArgumentException, IllegalAccessException,
			SecurityException, NoSuchFieldException {
		Field f = object.getClass().getDeclaredField(name);
		boolean accessFlag = f.isAccessible();
		f.setAccessible(true);
		Object o = f.get(object);
		f.setAccessible(accessFlag);
		return o;
	}

	/**
	 * 设置对象的某个属性的值
	 * 
	 * @param name
	 *            属性名
	 * @param value
	 *            值
	 * @param object
	 *            对象
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public static Object setValueByName(String name, Object value, Object object)
			throws IllegalArgumentException, IllegalAccessException,
			SecurityException, NoSuchFieldException {
		Field f = object.getClass().getDeclaredField(name);
		return setValueByName(f, value, object);
	}
	/**
	 * 设置对象的某个属性的值
	 * 
	 * @param field
	 *            属性
	 * @param value
	 *            值
	 * @param object
	 *            对象
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public static Object setValueByName(Field field, Object value, Object object)
			throws IllegalArgumentException, IllegalAccessException,
			SecurityException, NoSuchFieldException {
		boolean accessFlag = field.isAccessible();// 获得原始权限
		field.setAccessible(true);// 权限设置为可访问
		field.set(object, value);
		field.setAccessible(accessFlag);// 还原权限
		return object;
	}
	/**
	 * 通过方法赋值
	 * @param field
	 * @param value
	 * @param object
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static Object setValueByNameInokeMethod(Field field, Object value, Object object) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		StringBuilder methodName = new StringBuilder("set");
		methodName.append(firstLetterToUpper(field.getName()));
		Method method = object.getClass().getMethod(methodName.toString(), field.getType());
		method.invoke(object, value);
		return object;
	}
	/**
	 * 通过方法取值
	 * @param field
	 * @param object
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static Object getValueByNameInokeMethod(Field field, Object object) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		StringBuilder methodName = new StringBuilder("get");
		methodName.append(firstLetterToUpper(field.getName()));
		Method method = object.getClass().getMethod(methodName.toString());
		return method.invoke(object);
	}
	/**
	 * 获得所有成员变量，包括所有超类
	 * @param clazz
	 * @return
	 */
	public static List<Field> getAllFields(Class<?> clazz){
		List<Field> result = new ArrayList<Field>();
		if(clazz==null){
			return result;
		}
		for(Field f :clazz.getDeclaredFields()){
			result.add(f);
		}
		result.addAll(getAllFields(clazz.getSuperclass()));
		return result;
	}
	
	/**
	 * 首字母大写
	 * @param str
	 * @return
	 */
	public static String firstLetterToUpper(String str){
        char[] array = str.toCharArray();
        array[0] -= 32;
        return String.valueOf(array);
    }
}